package com.star.spring.websocket.client;

import com.alibaba.fastjson2.JSON;
import com.star.spring.websocket.model.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.client.WebSocketClient;

import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class WebSocketClientHandler implements org.springframework.web.socket.WebSocketHandler {

    @Value("${websocket.client.server-url:ws://localhost:8080/websocket}")
    private String serverUrl;

    @Value("${websocket.client.reconnect-interval:5000}")
    private long reconnectInterval;

    @Autowired
    private WebSocketClient webSocketClient;

    private WebSocketSession session;
    private boolean isConnected = false;
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    /**
     * 连接到WebSocket服务器
     */
    public void connect() {
        if (isConnected) {
            log.info("WebSocket客户端已经连接");
            return;
        }

        try {
            log.info("正在连接到WebSocket服务器: {}", serverUrl);
            session = webSocketClient.doHandshake(this, null, serverUrl).get();
            isConnected = true;
            log.info("WebSocket客户端连接成功");
        } catch (Exception e) {
            log.error("WebSocket客户端连接失败", e);
            scheduleReconnect();
        }
    }

    /**
     * 断开连接
     */
    public void disconnect() {
        if (session != null && session.isOpen()) {
            try {
                session.close();
                log.info("WebSocket客户端连接已关闭");
            } catch (IOException e) {
                log.error("关闭WebSocket客户端连接失败", e);
            }
        }
        isConnected = false;
    }

    /**
     * 发送消息
     */
    public void sendMessage(Message message) {
        if (session != null && session.isOpen()) {
            try {
                String jsonMessage = JSON.toJSONString(message);
                session.sendMessage(new TextMessage(jsonMessage));
                log.info("客户端发送消息: {}", jsonMessage);
            } catch (IOException e) {
                log.error("客户端发送消息失败", e);
                handleConnectionError();
            }
        } else {
            log.warn("WebSocket客户端未连接，无法发送消息");
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        this.session = session;
        isConnected = true;
        log.info("WebSocket客户端连接建立");
        
        // 发送连接确认消息
        Message connectMessage = new Message();
        connectMessage.setType("CLIENT_CONNECT");
        connectMessage.setContent("客户端连接确认");
        connectMessage.setTimestamp(System.currentTimeMillis());
        sendMessage(connectMessage);
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String payload = message.getPayload().toString();
        log.info("客户端收到消息: {}", payload);
        
        try {
            Message receivedMessage = JSON.parseObject(payload, Message.class);
            handleReceivedMessage(receivedMessage);
        } catch (Exception e) {
            log.error("客户端解析消息失败: {}", payload, e);
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket客户端传输错误", exception);
        handleConnectionError();
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("WebSocket客户端连接关闭，状态: {}", closeStatus);
        isConnected = false;
        this.session = null;
        
        // 如果不是主动断开，则尝试重连
        if (closeStatus.getCode() != CloseStatus.NORMAL.getCode()) {
            scheduleReconnect();
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 处理接收到的消息
     */
    private void handleReceivedMessage(Message message) {
        switch (message.getType()) {
            case "WELCOME":
                log.info("收到服务器欢迎消息: {}", message.getContent());
                break;
            case "ECHO_RESPONSE":
                log.info("收到服务器回显: {}", message.getContent());
                break;
            case "BROADCAST":
                log.info("收到广播消息: {}", message.getContent());
                break;
            default:
                log.info("收到未知类型消息: {}", message.getType());
        }
    }

    /**
     * 处理连接错误
     */
    private void handleConnectionError() {
        isConnected = false;
        if (session != null) {
            try {
                session.close();
            } catch (IOException e) {
                log.error("关闭错误连接失败", e);
            }
            session = null;
        }
        scheduleReconnect();
    }

    /**
     * 安排重连
     */
    private void scheduleReconnect() {
        log.info("安排{}毫秒后重连", reconnectInterval);
        scheduler.schedule(() -> {
            if (!isConnected) {
                log.info("开始重连...");
                connect();
            }
        }, reconnectInterval, TimeUnit.MILLISECONDS);
    }

    /**
     * 检查连接状态
     */
    public boolean isConnected() {
        return isConnected && session != null && session.isOpen();
    }

    /**
     * 获取连接状态信息
     */
    public String getConnectionStatus() {
        if (isConnected()) {
            return "已连接";
        } else {
            return "未连接";
        }
    }
} 